home *** CD-ROM | disk | FTP | other *** search
- /* LDEF Resource.c */
- /*
- * Copyright © 1989, 1990 Martin Minow and MacTutor.
- *
- * You may use this software in any application and
- * redistribute this source without restriction as long
- * as this copyright and permission notice remains intact
- * and the source is not redistributed for profit and you
- * assume all responsibility for the proper operation of
- * this software.
- *
- * Written in Think C. Set Tabs every 2 characters.
- */
- #define FORMAT TRUE_RESOURCE
- #ifdef DOCUMENTATION
-
- Usage
-
- void /* COMPILED only */
- add_LDEF(list) /* ... */
- ListHandle list; /* ... */
-
- void /* COMPILED only */
- remove_LDEF(list) /* ... */
- ListHandle list; /* ... */
-
- void /* FAKE_RESOURCE only */
- setup_LDEF(id) /* ... */
- int id; /* ... */
-
- User-provided function:
-
- void
- my_draw_function(
- Rect *lRrect, /* Drawing rectangle */
- Cell lCcell, /* Cell to redraw */
- short lDataOffset, /* Offset to cell to redraw */
- short lDataLen, /* Length of cell's data */
- ListHandle lHandle /* The list handle */
- )
-
- Note: this is called using C calling conventions --
- mostly because I couldn't convince Think C to compile
- it as a pascal function.
-
- Description
-
- Initialize your list as follows:
-
- setup_LDEF(resource_id); /* FAKE_RESOURCE only */
- resource_id = 0; /* COMPILED only */
- resource_id = <id>; /* FAKE_ or TRUE_RESOURCE */
- TextFont( ... ); /* Font of your choice */
- TextSize( ... ); /* Whatever you choose */
- myList = LNew(
- &box, /* Display dimensions */
- &dimension, /* Shape (rows, cols) */
- cell, /* Cell shape on screen */
- resource_id, /* List func, if any */
- dialog, /* The window */
- FALSE, /* Don't draw yet */
- FALSE, /* No grow box */
- FALSE, /* no horizontal scroll */
- TRUE /* Vertical scroll */
- );
- add_LDEF(myList); /* COMPILED only */
- (**myList).refCon = my_draw_function;
-
- Now, whenever the list manager needs to draw something,
- the LDEF handler function will be called. If the list
- refCon is zero, the LDEF handler operates identically
- to the standard, except that it preserves font and font
- size information. This is all you need if you wish to
- draw a text list in a dialog using other than the system
- font.
-
- If the refCon is set to a user function, the function
- will be called after the following initialization has
- been completed:
-
- • The pen is "normal" and positioned properly to draw
- the text.
- • The cell to be drawn is locked.
- • The drawing rectangle is erased.
- • The font and font size are set to values in the list's
- port.
-
- The simplest user function need only draw the cell:
-
- DrawText(*((**lHandle).cells), lDataOffset, lDataLen);
-
- A more complicated user function may get the cell's
- contents (using LGetCell) and perform some function
- based on that information.
-
- If you have compiled the LDEF function, be sure to call
- remove_LDEF() before exiting: otherwise, your program
- will crash:
-
- remove_LDEF(myList); /* COMPILED only */
- LDispose(myList);
-
- Author
-
- Martin Minow
-
- Thanks to Amanda Walker, InterCon Corporation,
- for the call-back idea.
-
- #endif
-
- /*
- * These values configure the demo program: that way
- * we only need to write one piece of code.
- */
- #define COMPILED 0
- #define FAKE_RESOURCE 1
- #define TRUE_RESOURCE 2
- #include <Color.h>
- #define NIL 0
- typedef short word;
- /*
- * The current ListHandle is always in local variable list.
- */
- #define LIST (**list)
-
- /*
- * This structure defines the fake LDEF resource.
- */
- typedef struct {
- word instruction;
- void (*function)();
- } LDEF_record, *LDEF_pointer, **LDEF_handle;
-
- /*
- * Externally visible functions.
- */
- #if FORMAT == FAKE_RESOURCE
- void setup_LDEF(int);
- #endif
- #if FORMAT == COMPILED
- void add_LDEF(ListHandle);
- void remove_LDEF(ListHandle);
- #endif
- #if FORMAT == TRUE_RESOURCE
- pascal void main(
- int, Boolean, Rect *, Cell, int, int, ListHandle);
- #else
- static pascal void myListDef(
- int, Boolean, Rect *, Cell, int, int, ListHandle);
- #endif
-
- /*
- * Define the type of the callback function. Amanda Walker
- * calls this "the cast from hell", and with good reason.
- */
- typedef void (* FUNC)(Rect *, Cell, word, word, ListHandle);
-
- #if FORMAT == COMPILED
- /*
- * Call this after calling LNew for any list that is to
- * use this list definition routine. It creates a handle
- * and fills it with enough code to jump to myListDef.
- * Note that we do not use a LDEF resource.
- */
- void
- add_LDEF(list)
- ListHandle list;
- {
- LDEF_handle ldef;
-
- ldef = (LDEF_handle) NewHandle(sizeof (LDEF_record));
- if (ldef != NIL) {
- (**ldef).instruction = 0x4EF9; /* JMP instruction */
- (**ldef).function = myListDef;
- LIST.listDefProc = (Handle) ldef;
- }
- }
-
- /*
- * Be sure to call this before deleting the list.
- * Otherwise, you'll have random program crashes.
- */
- void
- remove_LDEF(list)
- ListHandle list;
- {
- LIST.listDefProc = NIL;
- }
- #endif
-
- #if FORMAT == FAKE_RESOURCE
- /*
- * Call this once when your application starts if it uses
- * the list definition function. You only need to call it
- * once, even if several lists use this function.
- */
- void
- setup_LDEF(id)
- int id;
- {
- LDEF_handle ldef;
-
- ldef = (LDEF_handle) Get1Resource('LDEF', id);
- if (ldef != NIL
- && GetHandleSize(ldef) == sizeof (LDEF_record)) {
- (**ldef).instruction = 0x4EF9;
- (**ldef).function = myListDef;
- HNoPurge(ldef);
- }
- }
- #endif
-
- /*
- * myListDef() is called by the Macintosh list manager. It
- * is identical to the standard function, except that it
- * preserves font and size and may call a user function
- * for strange data formatting.
- */
- #if FORMAT == TRUE_RESOURCE
- pascal void main
- #else
- static pascal void myListDef
- #endif
- (message, select, rect, cell, offset, length, list)
- int message; /* List manager action */
- Boolean select; /* TRUE if cell is to be selected */
- Rect *rect; /* Rectangle to draw cell in */
- Cell cell; /* The selected cell */
- int offset; /* Start of data in the list */
- int length; /* Number of bytes to draw */
- ListHandle list; /* The list itself. */
- {
- int old_font;
- int old_size;
- FontInfo info;
- Point where;
- int lock_state;
- long saved_A5;
- GrafPtr old_port;
-
- /*
- * This is needed so the drawing code can find the
- * application globals.
- */
- saved_A5 = SetCurrentA5();
- /*
- * If we're compiled, we don't have valid QuickDraw
- * globals (such as thePort), so we use the current
- * port information from the ListRecord.
- */
- GetPort(&old_port);
- SetPort(LIST.port);
- old_font = LIST.port->txFont; /* Save the old */
- old_size = LIST.port->txSize; /* font and size */
- /*
- * Editorial note: '--' is the C decrement operator,
- * not the typeographer's "long dash".
- */
- if (message-- == 0) { /* lInitMsg */
- /*
- * Initialization: save indentation. Note: do not
- * touch select, rect, cell, offset, or length.
- */
- GetFontInfo(&info);
- LIST.indent.v = info.ascent;
- LIST.indent.h = 4; /* Arbitrary */
- }
- else if (message-- == 0) { /* lDrawMsg */
- where = topLeft(*rect);
- AddPt(LIST.indent, &where);
- MoveTo(where.h, where.v);
- PenNormal();
- lock_state = HGetState(LIST.cells);
- HLock(LIST.cells);
- EraseRect(rect);
- TextFont((LIST.port)->txFont);
- TextSize((LIST.port)->txSize);
- /*
- * We're ready to roll. If there's a user-provided
- * function, call it. Otherwise, just draw text.
- */
- if (LIST.refCon == NIL)
- DrawText(*(LIST.cells), offset, length);
- else {
- (*(FUNC) (LIST.refCon))
- (rect, cell, offset, length, list);
- }
- HSetState(LIST.cells, lock_state);
- if (select) /* If selected */
- goto hilite; /* go hilite it */
- }
- else if (message-- == 0) { /* lHiliteMsg */
- hilite:
- HiliteMode &= ~(1 << hiliteBit); /* IM V-62 */
- InvertRect(rect);
- }
- TextFont(old_font);
- TextSize(old_size);
- SetA5(saved_A5);
- }
-
-